#ifndef _3D_CAMERA_H_
#define _3D_CAMERA_H_

#include <stdint.h>
#include <stdbool.h>
#include "3d_unit.h"

//投影结果
typedef enum
{
    //正常入屏
    D3C_RESULT_INSIDE = 0x00,
    //出屏方式,可能出现多种情况一起的结果
    D3C_RESULT_OUT_OF_TOP = 0x01,
    D3C_RESULT_OUT_OF_BOTTOM = 0x02,
    D3C_RESULT_OUT_OF_LEFT = 0x04,
    D3C_RESULT_OUT_OF_RIGHT = 0x08,
    D3C_RESULT_OUT_OF_NEAR = 0x10,
    D3C_RESULT_OUT_OF_FAR = 0x20,
} D3CameraResult;

class D3Camera : public D3Unit
{
public:
    /*
     *  参数:
     *      width,height: 屏幕宽高
     *      far: 远端视野消失点,即模型放在这个距离时在屏幕就只剩下一个点了
     */
    D3Camera(int32_t width, int32_t height, int32_t far = 1000);

    bool IsInside(int32_t x, int32_t y);
    bool IsInside(int32_t *result, int32_t len);

    int32_t GetWidth();
    void SetWidth(int32_t width);
    int32_t GetHeight();
    void SetHeight(int32_t height);

    /*
     *  模型与屏幕距离为0时的显示大小倍数
     *  例如模型宽10像素,与屏幕0距离,而该倍数为1,则在屏幕显示也是10像素
     *  数值必须大于0
     */
    float GetZoom();
    void SetZoom(float zoom);

    /*
    *  透视投影,把三维坐标映射到相机屏幕
    *  参数:
    *       xyz: 待映射三维坐标(需相对于相机坐标系,若为原始空间坐标,需先camera->Transfer(xyz)处理)
    *       retXY: 返回的屏幕坐标,屏幕左上角为(0,0),注意返回坐标包含负数等超出屏幕范围的坐标
    *       retDepth: 返回深度,范围0.0~1.0
    *  返回: 解析见 D3CameraResult 定义
    */
    int32_t Project(float xyz[3], int32_t retXY[2], float retDepth[1]);
    //批量处理模式,注意count为坐标点个数
    void ProjectArray(float *xyz, int32_t *retXY, float *retDepth, int32_t count);

private:
    int32_t width, height;
    int32_t widthHalf, heightHalf;
    float far;
    float zoom = 2;
};

#endif // _3D_CAMERA_H_
